<?php

namespace App\Service;

use App\Extend\Token;
use App\Model\SaRole;
use App\Extend\Predis;
use App\Model\SaAdmin;
use App\Model\SaAdminLoginLog;
use App\Model\SaIndexRoleAdmin;
use App\Exceptions\ApiException;

class AdminService
{
    /**
     * 获取管理员列表.
     *
     * @param $param
     * @param $limit
     *
     * @return mixed
     */
    public static function getAdminList($reqData)
    {
        $page     = $reqData['page']     ?? 1;
        $perPage  = $reqData['per_page'] ?? 15;

        $list  = SaAdmin::query()
            ->when($reqData, function ($query) use ($reqData) {
                if (!empty($reqdata['username'])) {
                    $query->where('username', '=', $reqData['username']);
                }
            })
            ->paginate($perPage, ['id', 'username', 'role_id', 'status', 'last_login', 'last_ip', 'created_at'], 'page', $page);
        $result =  $list->toArray();

        //格式化数据
        SaAdmin::formatList($result['data']);

        return $result;
    }

    /**
     * 获取管理员信息.
     *
     * @param $token
     *
     * @return array|bool
     *
     * @throws \Throwable
     */
    public static function getAdminInfoParse($token)
    {
        $fullToken = json_decode(base64_decode($token), true); //此时token包含[ "sign" => "d5c6d6f066304246360c81edfc9bc8d8","timestamp" => 1745378755, "token" => "xzx"]

        throw_if(!$fullToken, new ApiException('用户登录信息已过期'));
        throw_if((time() - $fullToken['timestamp']) > 7200, new ApiException('用户登录信息已过期,请重新登录'));

        $result    = Token::checkToken($fullToken['token']);
        throw_if(!$result, new ApiException('token异常'));

        $result   = (array) $result;
        $userInfo = (array) $result['data'];
        // 从redis获取信息
//        $key   = 'ADMIN:UID:' . $userInfo['id'];
//        $redis = new Predis();
//        $data  = $redis->get($key);
//        throw_if(!$data, new ApiException('登录失效，请重新登录'));
//        $data = json_decode($data, true);

        // 单点登录
//        if ($userToken != $data['token']) {
//            return failJson('登录失效，请重新登录', 401);
//        }

        // 刷新有效期
//        $redis->expire($key, 7200);

        // 验证用户状态
        $admin = self::getInfoById($userInfo['id']);
        throw_if((1 != $admin['status'] || 1 != $admin['role_status']), new ApiException('登录失效，请重新登录'));

        return $admin;
    }

    /**
     * 根据Id获取管理员信息.
     *
     * @param $id
     *
     * @return array|bool
     */
    public static function getInfoById($id)
    {
        return SaAdmin::getInfo(['id' => $id]);
    }

    /**
     * 管理员登录验证
     *
     * @param $username
     * @param $password
     *
     * @return mixed
     */
    public static function loginCheck($username, $password)
    {
        throw_if(empty($username) || empty($password), new ApiException('参数不能为空'));

        // 获取管理员信息
        $where = ['username' => $username];
        $info  = SaAdmin::getInfo($where);
        throw_if(!$info, new ApiException('账号或密码错误'));

        // 验证密码
        $encrypt = md5($password . $info['safe']);
        throw_if($encrypt != $info['password'], new ApiException('账号或密码错误'));

        // 验证管理员状态
        throw_if(!$info['status'], new ApiException('账号异常'));

        // 验证角色状态
        throw_if(!$info['role_status'], new ApiException('角色状态异常'));

        // 获取用户拥有权限
        $permission = RoleService::getPermission($info['role_id'], $info['is_admin']);
        throw_if(!count($permission['list']), new ApiException('暂无权限'));

        unset($info['password']);
        unset($info['safe']);

        return $info;
    }

    /**
     * 记录管理员登录信息.
     *
     * @param $info
     */
    public static function saveLoginInfo($info)
    {
        // 记录登录信息
        SaAdminLoginLog::saveInfo($info);

        // 更新登录信息
        $update['last_login'] = time();
        $update['last_ip']    = $info['ip'];
        SaAdmin::where(['username' => $info['username']])->increment('login_num', 1, $update);
    }

    /**
     * 添加管理员.
     *
     * @param $username
     * @param $password
     * @param $roleId
     * @param int $status
     *
     * @return mixed
     */
    public static function addAdmin($username, $password, $roleId, $status = 1, $isSystem = 0)
    {
        $roleIds = is_array($roleId) ? $roleId : explode(',', $roleId);
        // 检测是否重名
        $info = SaAdmin::getInfo(['username' => $username]);
        throw_if($info, new ApiException('此管理员已存在，请勿重复添加'));

        $loginAdmin        = $isSystem ? ['id' => 0, 'username' => 'system'] : HelperClass::getLoginAdmin();

        $safe              = randString();
        $encrypt           = md5($password . $safe);
        $data              = [
            'username'    => $username,
            'safe'        => $safe,
            'password'    => $encrypt,
            'status'      => $status,
            'creator_id'  => $loginAdmin['id'],
            'creator'     => $loginAdmin['username'],
        ];
        $adminId = SaAdmin::addAdmin($data);

        foreach ($roleIds as $rId) {
            $adminRoleIdx = [
                'admin_id'    => $adminId,
                'role_id'     => $rId,
                'creator_id'  => $loginAdmin['id'],
                'creator'     => $loginAdmin['username'],
            ];
            SaIndexRoleAdmin::query()->create($adminRoleIdx);
        }

        return true;
    }

    /**
     * 编辑管理员.
     *
     * @param $id
     * @param $roleId
     * @param $status
     * @param $password
     *
     * @return mixed
     */
    public static function editAdmin($id, $roleId, $status, $password)
    {
        // 验证管理员
        $info = SaAdmin::getInfo(['id' => $id]);
        throw_if(!$info, new ApiException('管理员不存在'));

        throw_if(1 == $info['is_admin'], new ApiException('无权修改超级管理员'));

        // 验证角色
        $role = SaRole::getInfo(['id' => $roleId]);
        throw_if(!$role, new ApiException('角色不存在'));
        throw_if(1 == $role['is_admin'], new ApiException('无权将角色设置为超级管理员'));

        if ($password) {
            $encrypt           = md5($password . $info['safe']);
            $admin['password'] = $encrypt;
        }
        $loginAdmin           = HelperClass::getLoginAdmin();
        $admin['status']      = $status;
        $admin['updater_id']  = $loginAdmin['id'];
        $admin['updater']     = $loginAdmin['username'];

        $res     = SaAdmin::editAdmin($id, $admin);
        $roleIds = is_array($roleId) ? $roleId : explode(',', $roleId);
        $oldRIds = SaIndexRoleAdmin::where(['admin_id' => $id])->pluck('role_id')->toArray();

        $addIds = array_diff($roleIds, $oldRIds);
        $delIds = array_diff($oldRIds, $roleIds);
        if ($addIds) {
            foreach ($addIds as $rId) {
                SaIndexRoleAdmin::query()->create([
                    'admin_id'    => $id,
                    'role_id'     => $rId,
                    'creator_id'  => $loginAdmin['id'],
                    'creator'     => $loginAdmin['username'],
                    'updater_id'  => $loginAdmin['id'],
                    'updater'     => $loginAdmin['username'],
                ]);
            }
        }
        if ($delIds) {
            SaIndexRoleAdmin::query()->where('admin_id', $id)->whereIn('role_id', $delIds)->delete();
        }

        return $res;
    }

    /**
     * 删除管理员.
     *
     * @param $id
     *
     * @return mixed
     *
     * @throws \Exception
     */
    public static function delAdminById($id)
    {
        // 获取被删除的管理员信息
        $info = SaAdmin::getInfo(['id' => $id]);
        throw_if($info && 1 == $info['is_admin'], new ApiException('无权删除超级管理员'));

        return SaAdmin::delAdmin($id);
    }

    /**
     * 修改管理员密码
     *
     * @param $id
     * @param $oldPassword
     * @param $password
     *
     * @return mixed
     */
    public static function changePassword($id, $oldPassword, $password)
    {
        // 验证原始密码
        $info = SaAdmin::getInfo(['id' => $id]);
        throw_if(!$info, new ApiException('数据不存在'));

        $encrypt = md5($oldPassword . $info['safe']);
        throw_if($encrypt != $info['password'], new ApiException('旧密码错误'));

        $safe              = randString();
        $loginAdmin        = HelperClass::getLoginAdmin();

        $admin = [
            'safe'       => $safe,
            'password'   => md5($password . $safe),
            'updater_id' => $loginAdmin['id'],
            'updater'    => $loginAdmin['username'],
        ];

        return SaAdmin::editAdmin($id, $admin);
    }
}
